#pragma clang diagnostic push
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
//
// Created by hugan on 2020/10/17.
//

#include "CommonUtil.h"

char *CommonUtil::getInputLine(const char *msg) {
    char input[255];
    while (true) {
        cout << msg << endl;
        cin.getline(input, sizeof(input), '\n');
        cout << "input:" << input << endl;
        //为temp动态分配内存（动态申请内存的变量可以跨函数使用）
        // malloc分配的内容在堆区，temp还是分配在栈区
        char *temp = (char *) malloc(sizeof(input));
        temp[0] = input[0];
        strcpy(temp, input);
        return temp;
    }
}

static void (*pExitFunction)();

void CommonUtil::startExitInputThread(void (pExitFunction2)()) {
    pExitFunction = pExitFunction2;
    _beginthreadex(nullptr, 0, [](VOID *pParam) -> unsigned __stdcall {
        cout << "exitInputThread.start" << endl;
        CommonUtil::getInputLine("===input anything to exit.===");
        pExitFunction();
        cout << "exitInputThread.out" << endl;
        _endthreadex(0);
    }, nullptr, 0, nullptr);
}

bool CommonUtil::FAILED2(const string& desc, HRESULT hr) {
    if (FAILED(hr)) {
        cout << desc << ".err=[";
        switch (hr) {
            case DIERR_INVALIDPARAM:
                cout << "DIERR_INVALIDPARAM";
                break;
            case DIERR_NOTINITIALIZED:
                cout << "DIERR_NOTINITIALIZED";
                break;
            case DIERR_OBJECTNOTFOUND:
                cout << "DIERR_OBJECTNOTFOUND";
                break;
            case DIERR_UNSUPPORTED:
                cout << "DIERR_UNSUPPORTED";
                break;
                //CreateDevice
            case DIERR_DEVICENOTREG:
                cout << "DIERR_DEVICENOTREG";
                break;
            case DIERR_NOINTERFACE:
                cout << "DIERR_NOINTERFACE";
                break;
            case DIERR_OUTOFMEMORY:
                cout << "DIERR_OUTOFMEMORY";
                break;
                //GetDeviceInfo
            case E_POINTER:
                cout << "E_POINTER";
                break;
                //GetDeviceState
            case CommonUtil::INPUT_LOST:
            case DIERR_INPUTLOST:
                cout << "DIERR_INPUTLOST";
                break;
            case DIERR_NOTACQUIRED:
                cout << "DIERR_NOTACQUIRED";
                break;
            case E_PENDING:
                cout << "E_PENDING";
                break;
                //Acquire??
                //common
            case E_FAIL:
                cout << "E_FAIL";
                //S_FALSE是表示成功!不是错误,E_FAIL才是错误
                break;
            default:
                cout << hr;
                break;
        }
        //@deprecated 不如使用自定义文本
//        TCHAR *formattedMsg = nullptr;
//        ::FormatMessage(
//                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
//                nullptr,
//                hr,
//                0,
//                ( LPTSTR )&formattedMsg,
//                0,
//                nullptr );
//
//        cout << ", " << formattedMsg;
        cout << "]" << endl;
        return true;
    } else {
        return false;
    }
}

void CommonUtil::printDeviceState(DIJOYSTATE2 *pState, bool allField) {
    DIJOYSTATE2 state = *pState;
    /**
    * AXIS.XY: 左摇杆
    *  lX,lY
    * XInput手柄
    *   ROTATION.XT:右摇杆
    *    lRx,lRy
    *   Z_AXIS:LR2
    *    lZ
    * DInput手柄
    *
    * POV0:十字方向键
    *  rgdwPOV[0]
    * BUTTONS:除上面外的其他物理键,包括按下摇杆,支持多键同时按下
    *  rgbButtons[0,127]
    */
    cout << "deviceState[";
    bool printed = false;
    //摇杆
    if (state.lX || state.lY) {
        printed = true;
        cout << "    left stick.x=" << state.lX << ", y=" << state.lY << endl;
    }
    if (state.lRx || state.lRy) {
        printed = true;
        cout << "    right stick.x=" << state.lRx << ", y=" << state.lRy << endl;
    }
    if (state.lZ || state.lRz) {
        printed = true;
        cout << "    LR2(XInput) or right stick(DInput,HID).x=" << state.lZ << ", y=" << state.lRz << endl;
    }

    //十字方向键
    if (state.rgdwPOV[0] != 0xFFFFFFFF) {
        printed = true;
        cout << "    arrow=" << state.rgdwPOV[0] << endl;
    }

    //一般按键
    TCHAR strText[512] = {0};
    StringCchCopy(strText, 512, TEXT(""));
    for (int i = 0; i < 128; i++) {
        if (state.rgbButtons[i] & 0x80) {
            TCHAR sz[128];
            StringCchPrintf(sz, 128, TEXT("%02d "), i);
            StringCchCat(strText, 512, sz);
        }
    }
    if (strlen(strText)) {
        printed = true;
        cout << "    buttons=" << strText << endl;
    }

    if (allField) {
        //未实现
        cout << "allField: todo..." << endl;
    }
    if (!printed) {
        cout << "]" << endl;
    }
}
